package com.hcc.gateway.ops.controller;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.hcc.gateway.common.domain.DubboReq;
import com.hcc.gateway.common.utils.DubboUtils;
import com.hcc.gateway.domain.enums.ApiParamTypeEnum;
import com.hcc.gateway.domain.enums.ApiStatusEnum;
import com.hcc.gateway.domain.enums.HttpMethodEnum;
import com.hcc.gateway.domain.enums.ProtocolEnum;
import com.hcc.gateway.domain.po.ApiConfigPo;
import com.hcc.gateway.domain.req.ApiConfigQueryReq;
import com.hcc.gateway.domain.vo.ApiConfigFormVo;
import com.hcc.gateway.domain.resp.PageResult;
import com.hcc.gateway.domain.resp.RestResp;
import com.hcc.gateway.domain.resp.SelectResp;
import com.hcc.gateway.domain.vo.ApiConfigVo;
import com.hcc.gateway.domain.vo.ParamTypeConfigVo;
import com.hcc.gateway.service.ApiConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * ApiConfigController
 *
 * @author shengjun.hu
 * @date 2022/1/5
 */
@Slf4j
@RestController
@RequestMapping("/apiManage")
public class ApiConfigController {

    @Autowired
    private ApiConfigService apiConfigService;

    @GetMapping("/protocols")
    public RestResp<List<SelectResp>> findProtocols() {
        return RestResp.success(
                Arrays.stream(ProtocolEnum.values())
                        .map(p -> new SelectResp(p.getDesc(), p.name()))
                        .collect(Collectors.toList())
        );
    }

    @GetMapping("/statuses")
    public RestResp<List<SelectResp>> findApiStatus() {
        return RestResp.success(
                Arrays.stream(ApiStatusEnum.values())
                        .map(p -> new SelectResp(p.getDesc(), p.name()))
                        .collect(Collectors.toList())
        );
    }

    @GetMapping("/httpMethods")
    public RestResp<List<SelectResp>> findHttpMethods() {
        return RestResp.success(
                Arrays.stream(HttpMethodEnum.values())
                        .map(p -> new SelectResp(p.name(), p.name()))
                        .collect(Collectors.toList())
        );
    }

    @GetMapping("/paramTypes")
    public RestResp<List<SelectResp>> findParamTypes() {
        return RestResp.success(
                Arrays.stream(ApiParamTypeEnum.values())
                        .map(p -> new SelectResp(p.getCode(), p.getCode()))
                        .collect(Collectors.toList())
        );
    }

    @PostMapping("/validate")
    public RestResp<String> validateApiConfig(@RequestBody ApiConfigFormVo apiConfigFormVo) {
        if (StrUtil.isNotEmpty(apiConfigFormVo.getApiName())) {
            this.validateApiName(apiConfigFormVo);
        }
        if (StrUtil.isNotEmpty(apiConfigFormVo.getPath())) {
            this.validatePath(apiConfigFormVo);
        }

        return RestResp.success();
    }

    public void validateApiName(ApiConfigFormVo apiConfigFormVo) {
        ApiConfigPo curApiConfigPo = apiConfigService.getById(apiConfigFormVo.getId());
        boolean exists = apiConfigService.lambdaQuery()
                .eq(ApiConfigPo::getApiName, apiConfigFormVo.getApiName())
                .ne("UPDATE".equals(apiConfigFormVo.getMode()), ApiConfigPo::getApiName, curApiConfigPo.getApiName())
                .exists();
        Assert.isFalse(exists, "API名称已存在！");
    }

    public void validatePath(ApiConfigFormVo apiConfigFormVo) {
        ApiConfigPo curApiConfigPo = apiConfigService.getById(apiConfigFormVo.getId());
        boolean exists = apiConfigService.lambdaQuery()
                .eq(ApiConfigPo::getPath, apiConfigFormVo.getPath())
                .ne("UPDATE".equals(apiConfigFormVo.getMode()), ApiConfigPo::getPath, curApiConfigPo.getPath())
                .exists();
        Assert.isFalse(exists, "API路径已存在！");
    }

    @PostMapping("/create")
    public RestResp<String> createApi(@RequestBody ApiConfigFormVo apiConfigFormVo) {
        apiConfigService.saveOrUpdateApiConfig(apiConfigFormVo);
        return RestResp.success();
    }

    @PostMapping("/list")
    public RestResp<PageResult<ApiConfigVo>> findApi(@RequestBody ApiConfigQueryReq param) {
        return RestResp.success(apiConfigService.findApiConfigByPage(param));
    }

    @GetMapping("/online/{id}")
    public RestResp<String> online(@PathVariable("id") Long id) {
        apiConfigService.updateStatus(id, ApiStatusEnum.ONLINE);
        return RestResp.success();
    }

    @GetMapping("/offline/{id}")
    public RestResp<String> offline(@PathVariable("id") Long id) {
        apiConfigService.updateStatus(id, ApiStatusEnum.OFFLINE);
        return RestResp.success();
    }

    @GetMapping("/delete/{id}")
    public RestResp<String> delete(@PathVariable("id") Long id) {
        apiConfigService.removeById(id);
        return RestResp.success();
    }

    @GetMapping("/getFormApiConfig/{id}")
    public RestResp<ApiConfigFormVo> getFormApiConfig(@PathVariable("id") Long id) {
        ApiConfigFormVo apiConfigFormVo = apiConfigService.getApiConfigById(id);
        if (apiConfigFormVo == null) {
            return RestResp.success();
        }

        return RestResp.success(apiConfigFormVo);
    }

}
